#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libexif/exif-data.h>
#include <jpeglib.h>
#include <jerror.h>

// 设置 EXIF 标签的辅助函数
static void set_exif_tag(ExifData *exif_data, ExifIfd ifd, ExifTag tag, 
                        const char *value) {
    ExifEntry *entry;
    
    // 检查是否已存在该标签
    entry = exif_content_get_entry(exif_data->ifd[ifd], tag);
    
    // 如果标签不存在，创建新的
    if (entry == NULL) {
        entry = exif_entry_new();
        exif_content_add_entry(exif_data->ifd[ifd], entry);
        exif_entry_initialize(entry, tag);
    }
    
    // 设置标签值
    if (entry->format == EXIF_FORMAT_ASCII) {
        strncpy((char *)entry->data, value, entry->size);
        entry->data[entry->size - 1] = '\0';
    }
}

// 读取图片的 EXIF 信息
void read_exif_info(const char *filename) {
    ExifData *exif_data = exif_data_new_from_file(filename);
    if (!exif_data) {
        printf("无法从文件读取 EXIF 数据\n");
        return;
    }

    // 打印一些基本的 EXIF 信息
    ExifEntry *entry;
    
    // 相机制造商
    entry = exif_content_get_entry(exif_data->ifd[EXIF_IFD_0], EXIF_TAG_MAKE);
    if (entry) {
        char buf[1024];
        exif_entry_get_value(entry, buf, sizeof(buf));
        printf("相机制造商: %s\n", buf);
    }

    // 相机型号
    entry = exif_content_get_entry(exif_data->ifd[EXIF_IFD_0], EXIF_TAG_MODEL);
    if (entry) {
        char buf[1024];
        exif_entry_get_value(entry, buf, sizeof(buf));
        printf("相机型号: %s\n", buf);
    }

    // 拍摄时间
    entry = exif_content_get_entry(exif_data->ifd[EXIF_IFD_0], EXIF_TAG_DATE_TIME);
    if (entry) {
        char buf[1024];
        exif_entry_get_value(entry, buf, sizeof(buf));
        printf("拍摄时间: %s\n", buf);
    }

        // 曝光时间
    entry = exif_content_get_entry(exif_data->ifd[EXIF_IFD_0], EXIF_TAG_EXPOSURE_TIME);
    if (entry) {
        char buf[1024];
        exif_entry_get_value(entry, buf, sizeof(buf));
        printf("曝光时间: %s\n", buf);
    }

    // ISO 感光度
    entry = exif_content_get_entry(exif_data->ifd[EXIF_IFD_0], EXIF_TAG_ISO_SPEED_RATINGS);
    if (entry) {
        char buf[1024];
        exif_entry_get_value(entry, buf, sizeof(buf));
        printf("ISO 感光度: %s\n", buf);
    }

    // 光圈值
    entry = exif_content_get_entry(exif_data->ifd[EXIF_IFD_0], EXIF_TAG_FNUMBER);
    if (entry) {
        char buf[1024];
        exif_entry_get_value(entry, buf, sizeof(buf));
        printf("光圈值: %s\n", buf);
    }

    //EXIF_TAG_X_RESOLUTION
    entry = exif_content_get_entry(exif_data->ifd[EXIF_IFD_0], EXIF_TAG_X_RESOLUTION);
    if (entry) {
        char buf[1024];
        exif_entry_get_value(entry, buf, sizeof(buf));
        printf("EXIF_TAG_X_RESOLUTION: %s\n", buf);
    }
    //EXIF_TAG_Y_RESOLUTION
    entry = exif_content_get_entry(exif_data->ifd[EXIF_IFD_0], EXIF_TAG_Y_RESOLUTION);
    if (entry) {
        char buf[1024];
        exif_entry_get_value(entry, buf, sizeof(buf));
        printf("EXIF_TAG_Y_RESOLUTION: %s\n", buf);
    }
    //EXIF_TAG_GPS_ALTITUDE
    entry = exif_content_get_entry(exif_data->ifd[EXIF_IFD_0], EXIF_TAG_GPS_ALTITUDE);
    if (entry) {
        char buf[1024];
        exif_entry_get_value(entry, buf, sizeof(buf));
        printf("EXIF_TAG_GPS_ALTITUDE: %s\n", buf);
    }


    exif_data_unref(exif_data);
}

// 写入 EXIF 数据到 JPEG 文件
int write_jpeg_with_exif(const char *input_file, const char *output_file,
                        unsigned char *exif_data, unsigned int exif_len) {
    struct jpeg_decompress_struct srcinfo;
    struct jpeg_compress_struct dstinfo;
    struct jpeg_error_mgr jsrcerr, jdsterr;
    FILE *input_fp = NULL, *output_fp = NULL;
    unsigned char *buffer = NULL;
    JSAMPARRAY buffer_array = NULL;
    int ret = -1;

    // 打开输入文件
    if ((input_fp = fopen(input_file, "rb")) == NULL) {
        printf("无法打开输入文件\n");
        return -1;
    }

    // 打开输出文件
    if ((output_fp = fopen(output_file, "wb")) == NULL) {
        printf("无法打开输出文件\n");
        fclose(input_fp);
        return -1;
    }

    // 初始化解压缩对象
    srcinfo.err = jpeg_std_error(&jsrcerr);
    jpeg_create_decompress(&srcinfo);
    jpeg_stdio_src(&srcinfo, input_fp);

    // 初始化压缩对象
    dstinfo.err = jpeg_std_error(&jdsterr);
    jpeg_create_compress(&dstinfo);
    jpeg_stdio_dest(&dstinfo, output_fp);

    // 读取 JPEG 头
    jpeg_read_header(&srcinfo, TRUE);
    jpeg_start_decompress(&srcinfo);

    // 设置压缩参数
    dstinfo.image_width = srcinfo.output_width;
    dstinfo.image_height = srcinfo.output_height;
    dstinfo.input_components = srcinfo.output_components;
    dstinfo.in_color_space = srcinfo.out_color_space;

    jpeg_set_defaults(&dstinfo);
    jpeg_set_quality(&dstinfo, 95, TRUE); // 设置质量

    // 开始压缩
    jpeg_start_compress(&dstinfo, TRUE);

    // 写入 EXIF 数据
    if (exif_data && exif_len > 0) {
        jpeg_write_marker(&dstinfo, JPEG_APP0 + 1, exif_data, exif_len);
    }

    // 分配行缓冲区
    buffer_array = (*dstinfo.mem->alloc_sarray)
        ((j_common_ptr) &dstinfo, JPOOL_IMAGE,
         srcinfo.output_width * srcinfo.output_components, 1);

    // 逐行复制图像数据
    while (srcinfo.output_scanline < srcinfo.output_height) {
        jpeg_read_scanlines(&srcinfo, buffer_array, 1);
        jpeg_write_scanlines(&dstinfo, buffer_array, 1);
    }

    // 完成压缩
    jpeg_finish_compress(&dstinfo);
    jpeg_finish_decompress(&srcinfo);

    ret = 0;

    // 清理
    jpeg_destroy_compress(&dstinfo);
    jpeg_destroy_decompress(&srcinfo);
    fclose(input_fp);
    fclose(output_fp);

    return ret;
}

// 修改图片的 EXIF 信息
int modify_exif_info(const char *filename, const char *make, const char *model, 
                    const char *datetime) {
    ExifData *exif_data = exif_data_new();
    if (!exif_data) {
        printf("无法创建 EXIF 数据\n");
        return -1;
    }

    // 设置基本信息
    if (make) {
        set_exif_tag(exif_data, EXIF_IFD_0, EXIF_TAG_MAKE, make);
    }
    if (model) {
        set_exif_tag(exif_data, EXIF_IFD_0, EXIF_TAG_MODEL, model);
    }
    if (datetime) {
        set_exif_tag(exif_data, EXIF_IFD_0, EXIF_TAG_DATE_TIME, datetime);
    }
    /*
        // 添加曝光时间
    if (exposure_time) {
        set_exif_tag(exif_data, EXIF_IFD_0, EXIF_TAG_EXPOSURE_TIME, exposure_time);
    }
    // 添加 ISO 感光度
    if (iso) {
        set_exif_tag(exif_data, EXIF_IFD_0, EXIF_TAG_ISO_SPEED_RATINGS, iso);
    }
    // 添加光圈值
    if (fnumber) {
        set_exif_tag(exif_data, EXIF_IFD_0, EXIF_TAG_FNUMBER, fnumber);
    }
    */
    // 保存 EXIF 数据到缓冲区
    unsigned char *exif_data_buf;
    unsigned int exif_data_len;
    exif_data_save_data(exif_data, &exif_data_buf, &exif_data_len);

    // 创建临时文件名
    char temp_filename[1024];
    snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", filename);

    // 写入新的图片文件
    int ret = write_jpeg_with_exif(filename, temp_filename, exif_data_buf, exif_data_len);

    // 如果成功，替换原文件
    if (ret == 0) {
        remove(filename);
        rename(temp_filename, filename);
    } else {
        remove(temp_filename);
    }

    // 清理
    free(exif_data_buf);
    exif_data_unref(exif_data);
    return ret;
}

// 示例用法
int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("用法: %s <图片文件>\n", argv[0]);
        return 1;
    }

    // 读取现有的 EXIF 信息
    printf("读取 EXIF 信息:\n");
    read_exif_info(argv[1]);

    // 修改 EXIF 信息
    //printf("\n修改 EXIF 信息:\n");
   // modify_exif_info(argv[1], "luke","meng","2024:12:17 15:30:00");

    return 0;
} 

/*
jpeg 的lib
sudo apt-get install libexif-dev libjpeg-dev
# 在目标板上
sudo apt-get install libexif12 libjpeg62


# 在开发主机上
sudo apt-get install libexif-dev

# 在目标板上
sudo apt-get install libexif12

//编译

gcc exif_tool.c -o exif_tool -ljpeg -lexif

*/